package com.dhcc.DRGsHosp.facade.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dayatang.domain.InstanceFactory;
import org.dayatang.querychannel.QueryChannelService;
import org.dayatang.utils.Page;
import org.openkoala.security.shiro.CurrentUser;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;

import com.dhcc.DRGsHosp.application.ScheduleJobApplication;
import com.dhcc.DRGsHosp.core.domain.ScheduleJob;
import com.dhcc.DRGsHosp.facade.ScheduleJobFacade;
import com.dhcc.DRGsHosp.facade.dto.ScheduleJobDTO;
import com.dhcc.DRGsHosp.facade.impl.assembler.ScheduleJobAssembler;
import com.dhcc.DRGsHosp.infra.util.StringUtils;

/**
 * @ClassName: ScheduleJobFacadeImpl  
 * @Description ：    定时任务 ---业务逻辑层--实体类
 * @Date: 2018年10月11日 下午4:02:30  
 * @Author QiaoYiLong 
 * @Version 3.1.1 DHC-DRG
 */
//@Named("ScheduleJobFacadeImplliuhongjun20181025")
public class ScheduleJobFacadeImpl implements ScheduleJobFacade{

	public final static Logger log = Logger.getLogger(ScheduleJobFacadeImpl.class);

	@Autowired
	private  Scheduler scheduler;

	@Autowired
	private  ScheduleJobApplication scheduleJobApplication ;
	
	private QueryChannelService queryChannel;

    private QueryChannelService getQueryChannelService(){
       if(queryChannel==null){
          queryChannel = InstanceFactory.getInstance(QueryChannelService.class,"queryChannel");
       }
       return queryChannel;
    }

	/**
	 *  addJob.  
	 *  @Description：添加定时任务
	 *  @Author QiaoYiLong
	 *  @param jobId 
	 *  @Date:2018年10月11日下午4:30:59
	 */
	@Override
	public String addJob(Map<String,Object> condition) {
		ScheduleJob scheduleJob = new ScheduleJob();
		Date date = new Date();
		String jobName=""+condition.get("jobName");
		String jobGroup=""+condition.get("jobGroup");
		jobName=StringUtils.stringToAscii(jobName).replaceAll(",", "");
		jobGroup=StringUtils.stringToAscii(jobGroup).replaceAll(",", "");
		//时间+任务名 拼接为主键id
		scheduleJob.setJobId(jobName+"_"+jobGroup);
		scheduleJob.setJobName(""+condition.get("jobName"));
		scheduleJob.setJobGroup(""+condition.get("jobGroup"));
		scheduleJob.setDescription(""+condition.get("description"));
		scheduleJob.setBeanClass(""+condition.get("beanClass"));
		scheduleJob.setMethodName(""+condition.get("methodName"));
		scheduleJob.setCronExpression(""+condition.get("cronExpression"));
		scheduleJob.setJobData(""+condition.get("jobData"));
		scheduleJob.setCreateTime(date);
		scheduleJob.setUpdateTime(date);
		scheduleJob.setCreateUser(CurrentUser.getUserAccount());
		scheduleJob.setJobStatus(ScheduleJob.STATUS_RUNNING);
		scheduleJob.setJobExecuteTime(""+condition.get("jobExecuteTime"));
		String message = runJob(scheduleJob);
		addScheduleJob(scheduleJob);
		return message;
	}
	/**
	 *  pauseJob.  
	 *  @Description：暂停定时任务
	 *  @Author QiaoYiLong
	 *  @param jobId 
	 *  @Date:2018年10月11日下午4:30:59
	 */
	@Override
	public void pauseJob(String jobId) {
		if(null != jobId && !"".equals(jobId)){
			pauseScheduleJob(jobId);
		}
	}
    /**
     *  resumeJob.  
     *  @Description：恢复定时任务
     *  @Author QiaoYiLong
     *  @param jobId 
     *  @Date:2018年10月11日下午4:51:42
     */
	@Override
    public void resumeJob(String jobId) {
		if(null != jobId && !"".equals(jobId)){
			resumeScheduleJob(jobId);
		}
	}
	/**
	 * 删除定时任务
	 */
	@Override
	public void deleteJob(String jobId) {
		if(null != jobId && !"".equals(jobId)){
			String[] ids = jobId.split(",");
			for( String id : ids ){
				deleteScheduleJob(id);
			}
		}
	}
	/**
	 * 修改定时任务
	 */
	@Override
	public void updateJob(Map<String,Object> condition) {
		String jobId = (String)condition.get("jobId");
		if(null != jobId && !"".equals(jobId)){
			ScheduleJob scheduleJob = new ScheduleJob();
			Date date = new Date();
			scheduleJob.setJobId(""+condition.get("jobId"));
			scheduleJob.setJobName(""+condition.get("jobName"));
			scheduleJob.setJobGroup(""+condition.get("jobGroup"));
			scheduleJob.setDescription(""+condition.get("description"));
			scheduleJob.setBeanClass(""+condition.get("beanClass"));
			scheduleJob.setMethodName(""+condition.get("methodName"));
			scheduleJob.setCronExpression(""+condition.get("cronExpression"));
			scheduleJob.setJobData(""+condition.get("jobData"));
			scheduleJob.setJobStatus(""+condition.get("jobData"));
			scheduleJob.setUpdateTime(date);
			scheduleJob.setJobStatus(""+condition.get("jobStatus"));
			scheduleJob.setJobExecuteTime(""+condition.get("jobExecuteTime"));
			updateCron(scheduleJob);
		}
	}
	/**
	 * 暂停一个定时任务
	 */
    public void pauseScheduleJob(String jobId) {
        ScheduleJob scheduleJob = getScheduleJobByID(jobId);
        try {
            //暂停一个job
            JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            scheduler.pauseJob(jobKey);
            //保存定时任务状态
            scheduleJob.setJobStatus(ScheduleJob.STATUS_NOT_RUNNING);
            updateScheduleJob(scheduleJob);
        }catch (Exception e){
            log.error("CatchException:暂停  "+scheduleJob.getJobName()+" 任务失败",e);
        }
    }
	/**
	 * 恢复一个定时任务
	 */
    public void resumeScheduleJob(String jobId) {
        //修改定时任务状态
        ScheduleJob scheduleJob = getScheduleJobByID(jobId);
        try{
            //恢复一个定时任务
            JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            scheduler.resumeJob(jobKey);
            //保存定时任务状态
            scheduleJob.setJobStatus(ScheduleJob.STATUS_RUNNING);
            updateScheduleJob(scheduleJob);
        }catch (Exception e){
            log.error("CatchException:恢复定时任务  "+scheduleJob.getJobName()+" 失败",e);
        }
    }

	/**
	 * 立即执行一个定时任务
	 * 用所给的方法名，参数和执行时间等参数创建一个新的任务，执行完毕以后立即删除
	 */
	@Override
    public void runOnce(String jobId) {
        ScheduleJob scheduleJob = getScheduleJobByID(jobId);
        try{
        	if( null != scheduleJob ){
          	  String jobName = scheduleJob.getJobName();
          	  String jobGroup = scheduleJob.getJobGroup();
//          	  ScheduleJob newJob = new ScheduleJob();
//          	  newJob.setBeanClass(scheduleJob.getBeanClass());
//          	  newJob.setCronExpression(scheduleJob.getCronExpression());
//          	  newJob.setDescription(scheduleJob.getDescription());
//          	  newJob.setJobData(scheduleJob.getJobData());
//          	  newJob.setJobGroup(jobGroup);
//          	  newJob.setJobName(jobName);
//          	  newJob.setJobId("new"+scheduleJob.getJobId());
//          	  newJob.setJobStatus(scheduleJob.getJobStatus());
//          	  newJob.setMethodName(scheduleJob.getMethodName());
//          	//用原来的方法名，参数和执行时间等参数创建一个新的任务，执行完毕以后立即删除。
//        	  System.out.println(jobName + " 立即执行  添加新任务 =====");
//	    	  Class<QuartzJobFactory> clazz = QuartzJobFactory.class ;
//	    	  JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(jobName, jobGroup).usingJobData("data", newJob.getJobData()).build();
//	    	  jobDetail.getJobDataMap().put("scheduleJob", newJob);
//	    	  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(newJob.getCronExpression());
//	    	  CronTrigger trigger = TriggerBuilder.newTrigger().withDescription(newJob.getJobId().toString()).withIdentity(jobName, jobGroup).withSchedule(scheduleBuilder).build();
//	    	  //添加新的任务
//	    	  scheduler.scheduleJob(jobDetail, trigger);   
	    	  JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
	    	  //立即执行任务
	    	  scheduler.triggerJob(jobKey);
//	    	  //从调度器和任何相关触发器中删除标识的作业
//	    	  scheduler.deleteJob(jobKey);
        	}
        }catch (Exception e){
            log.error("CatchException:立即执行定时任务  "+scheduleJob.getJobName()+"  失败",e);
        }
    }

    /**
     *  updateCron.  
     *  @Description：更新时间表达式
     *  @Author QiaoYiLong
     *  @Date:2018年10月11日下午5:07:10
     */
    public void updateCron(ScheduleJob scheduleJob) {       
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            scheduler.rescheduleJob(triggerKey,trigger);
            //保存定时任务状态
            updateScheduleJob(scheduleJob);
        }catch(Exception e){
        	e.printStackTrace();
            log.error("CatchException:更新定时任务   "+scheduleJob.getJobName()+"  时间表达式失败",e);
        }finally {
        	
        }

    }
	/**
	 * 删除一个定时任务
	 */
	public void deleteScheduleJob(String jobId){
        ScheduleJob scheduleJob = getScheduleJobByID(jobId);
        try {
            //删除一个job
            JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            scheduler.deleteJob(jobKey);
            //保存定时任务状态
            scheduleJob.setJobStatus(ScheduleJob.STATUS_NOT_RUNNING);
            deleteScheduleJob(scheduleJob);
        }catch (Exception e){
            log.error("CatchException:删除定时任务   "+scheduleJob.getJobName()+" 失败",e);
        }		
	}
    /**
     * 新增定时任务
     */
	public void addScheduleJob(ScheduleJob scheduleJob){
		System.out.println(" addJob === ");
		scheduleJobApplication.creatScheduleJob(scheduleJob);
    }
    
    /**
     * 保存修改的定时任务内容
     */
	public void updateScheduleJob(ScheduleJob scheduleJob){
		scheduleJobApplication.updateScheduleJob(scheduleJob);
    }
    /**
     * 删除定时任务内容
     */
	public void deleteScheduleJob(ScheduleJob scheduleJob){
		scheduleJobApplication.removeScheduleJob(scheduleJob);
    }
    /**
     * 通过主键id查找定时任务
     * @param id
     * @return ScheduleJob
     */
	@Override
	public ScheduleJob getScheduleJobByID(String id){
        return scheduleJobApplication.getScheduleJob(id);
    }

	/**
	 *  findAllByCondition.  
	 *  @Description：取得全部定时任务信息
	 *  @Author QiaoYiLong
	 *  @return 
	 *  @Date:2018年10月11日下午5:21:21
	 */
	@Override
	public List<Map<String,Object>> findAllByCondition(Map<String,Object> condition){
		List<Map<String,Object>> listDto = scheduleJobApplication.findAllByCondition(condition);
        return listDto;
    }
	/**
	 * 获取分页数据
	 */
	@Override
	public Page<ScheduleJobDTO> pageQueryScheduleJob( int currentPage, int pageSize){
		List<Object> conditionVals = new ArrayList<Object>();
	   	StringBuilder jpql = new StringBuilder("select _timetask from ScheduleJob _timetask   where 1=1 ");		
	   	jpql.append(" order by _timetask.jobName");
       
		@SuppressWarnings("unchecked")
		Page<ScheduleJob> pages = getQueryChannelService().createJpqlQuery(jpql.toString())
				.setParameters(conditionVals).setPage(currentPage, pageSize).pagedList();
		   
        return new Page<ScheduleJobDTO>(pages.getStart(), pages.getResultCount(),pageSize, ScheduleJobAssembler.toDTOs(pages.getData()));
	}
	/**
     *  任务名称是否已经存在
     */
	@Override
	public boolean isScheduleJobExist(String jobName) {
		return scheduleJobApplication.isScheduleJobExist(jobName);
	}
	/**
	 *  @Discription：执行定时任务
	 *  @Author： liuhongjun
	 *  @param job
	 *  @return 返回执行结果信息
	 *  @Date:2018年10月14日下午9:21:38
	 */
	public String runJob(ScheduleJob job) {
		String message = "fail";
	    if (job == null || !ScheduleJob.STATUS_RUNNING.equals(job.getJobStatus())) {
	        	return "empty";
	    }
		try {
		      JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		      //如果已经存在
		      if(null != jobKey && scheduler.checkExists(jobKey)){
			      TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());	   
			      CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		    	  // Trigger已存在，那么更新相应的定时设置
		    	  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
		    	  // 按新的cronExpression表达式重新构建trigger
		    	  trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).usingJobData("data", job.getJobData()).withSchedule(scheduleBuilder).build();
		    	  // 按新的trigger重新设置job执行
		    	  scheduler.rescheduleJob(triggerKey, trigger);		    	  
		      }else{// 不存在，创建一个
//		    	  Class clazz = QuartzJobFactory.class ;
		    	  	Object object = null ;
			  		if (StringUtils.hasLength(job.getBeanClass())) {
						try {
							object = Class.forName(job.getBeanClass()).newInstance();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					if (object == null) {
						return "定时任务方法未定义" ;
					}
					
					Class<? extends Job> clazz = (Class<? extends Job>)object.getClass();
		    	  JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getJobName(), job.getJobGroup()).usingJobData("data", job.getJobData()).build();
		    	  //放入参数，运行时的方法可以获取
		    	  jobDetail.getJobDataMap().put("scheduleJob", job);
		    	  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
		    	  CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();
		    	  scheduler.scheduleJob(jobDetail, trigger);		    	  
		      }
		      message = "success";
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		return message;
	}
	/**
	 *  initQuartzJob.  
	 *  @Description：项目启动时，自动加载数据库中配置的定时任务
	 *  @Author QiaoYiLong 
	 *  @Date:2018年10月11日上午10:18:02
	 */
	public void initScheduleJob(){
		ScheduleJob scheduleJob = new ScheduleJob();
		scheduleJob.setJobStatus(ScheduleJob.STATUS_RUNNING);// 已发布的定时任务
	    List<ScheduleJob> jobList = scheduleJobApplication.findAllScheduleJobByCondition(scheduleJob);
	    for (ScheduleJob job : jobList) {
	    	String  msg=runJobAuto(job);
	    	System.out.println("任务返回信息"+msg);
	    }
	}
	/**
	 *  @Discription：系统启动的时候自动执行
	 *  @Author： liuhongjun
	 *  @param job
	 *  @return
	 *  @Date:2018年10月25日上午11:58:18 
	 */
	public String runJobAuto(ScheduleJob job) {
		String message = "fail";
	    if (job == null ) {
	        	return "empty";
	    }
		try {
		      TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());	   
		      CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		      // 不存在，创建一个
		      if (null == trigger) {
		    	  	Object object = null ;
			  		if (StringUtils.hasLength(job.getBeanClass())) {
						try {
							object = Class.forName(job.getBeanClass()).newInstance();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					if (object == null) {
						return "定时任务方法未定义" ;
					}
					
					Class<? extends Job> clazz = (Class<? extends Job>)object.getClass();
		    	  JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getJobName(), job.getJobGroup()).build();
		    	  jobDetail.getJobDataMap().put("scheduleJob", job);
		    	  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
		    	  trigger = TriggerBuilder.newTrigger().withDescription(job.getJobId().toString()).withIdentity(job.getJobName(), job.getJobGroup())
		            .withSchedule(scheduleBuilder).build();
		    	  scheduler.scheduleJob(jobDetail, trigger);
		      } else {
		    	  // Trigger已存在，那么更新相应的定时设置
		    	  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
		    	  // 按新的cronExpression表达式重新构建trigger
		    	  trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
		    	  // 按新的trigger重新设置job执行
		    	  scheduler.rescheduleJob(triggerKey, trigger);
		      }
		      //如果是非运行状态，则将任务设为暂停
		      if(!ScheduleJob.STATUS_RUNNING.equals(job.getJobStatus())){
		            JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		            if(null != jobKey && scheduler.checkExists(jobKey)){
		            	scheduler.pauseJob(jobKey);
		            }
		      }
		      message = "success";
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		return message;
	}
}
